home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / msjv6-5.zip / WINDOS.ZIP / BASED.C < prev    next >
C/C++ Source or Header  |  1991-09-01  |  4KB  |  136 lines

  1. /* 
  2. BASED.C -- based pointer routines for Windows
  3. from Microsoft Systems Journal, September 1991
  4. Andrew Schulman (andrew@pharlap.com)
  5. */
  6.  
  7. #include <windows.h>
  8. #include <malloc.h>
  9. #include <dos.h>
  10. #include "winio.h"
  11.  
  12. #ifdef __BORLANDC__
  13. #include "based.h"
  14. #endif
  15.  
  16. /* If segm==0 then use current data segment */
  17. #define SET_DS(segm) \
  18.     if (segm) \
  19.     _asm { \
  20.     _asm push ds \
  21.     _asm mov ax, segm \
  22.     _asm mov ds, ax \
  23.     }
  24.     
  25. #define RESTORE_DS(segm) \
  26.     if (segm) _asm { \
  27.         _asm pop ds \
  28.         }
  29.  
  30. static unsigned alloc_flags = GMEM_MOVEABLE | GMEM_NODISCARD | GMEM_ZEROINIT;
  31.  
  32. /* Allocate a based heap, and return a segment value to be used
  33.    by subsequent based-heap functions */
  34. _segment _bheapseg(size_t size)
  35. {
  36.     WORD blk;
  37.     WORD locked;
  38.     void far *fp;
  39.     blk = GlobalAlloc(alloc_flags, size);
  40.     if (blk == 0)
  41.         return -1;
  42.     if ((fp = GlobalLock(blk)) == NULL)
  43.     {
  44.         GlobalFree(blk);
  45.         return -1;
  46.     }
  47.     locked = FP_SEG(fp);
  48.     if (LocalInit(locked, 0, size-1) == 0) /* calls GlobalLock again */
  49.     {
  50.         GlobalUnlock(blk);
  51.         GlobalFree(blk); 
  52.         return -1;
  53.     }
  54.     /* succeeded -- return selector (not handle) */
  55.     return locked;
  56. }
  57.  
  58. /* Free a based heap */
  59. int _bfreeseg(_segment seg)
  60. {
  61.     HANDLE h = GlobalHandle(seg);   /* turn selector back into handle */
  62.     GlobalUnlock(h);
  63.     GlobalUnlock(h);  // LocalInit does lock; undo it
  64.     return (GlobalFree(h) == NULL) ? 0 : -1;
  65. }
  66.  
  67. /* Allocate a block of memory from a heap; the segment value must have
  68.    been previously returned by _bheapseg */
  69. void _based(void) *_bmalloc(_segment segm, size_t size)
  70. {
  71.     unsigned ret;
  72.     SET_DS(segm);
  73.     if (ret = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, size))
  74.         ret = (unsigned) LocalLock(ret);
  75.     RESTORE_DS(segm);
  76.     winio_yield();
  77.     return (void _based(void) *) ret;
  78. }
  79.  
  80. /* Allocate storage for an array, zero-initialize the elements of the
  81.    array, and return a based pointer to the array */
  82. void _based(void) *_bcalloc(_segment segm, size_t num, size_t size)
  83. {
  84.     return _bmalloc(segm, num * size);
  85. }
  86.  
  87. /* Free an allocated block */
  88. void _bfree(_segment segm, void _based(void) *memblock)
  89. {
  90.     if (((unsigned) memblock) == 0xFFFF)
  91.         return;
  92.     SET_DS(segm);
  93.     LocalUnlock((WORD) memblock);
  94.     LocalFree((WORD) memblock);
  95.     RESTORE_DS(segm);
  96.     winio_yield();
  97. }
  98.  
  99. /* Helper function used by _bexpand and _brealloc */
  100. static void _based(void) *_bresize(_segment segm, 
  101.     void _based(void) *memblock, size_t size, WORD wFlags)
  102. {
  103.     unsigned ret;
  104.     SET_DS(segm);
  105.     ret = (unsigned) LocalReAlloc((char near *) memblock, size, 
  106.         wFlags | LMEM_ZEROINIT);
  107.     RESTORE_DS(segm);
  108.     winio_yield();
  109.     return (void _based(void) *) ret;
  110. }
  111.  
  112. /* Expand or shrink an allocated block in place */
  113. void _based(void) *_bexpand(_segment segm, 
  114.     void _based(void) *memblock, size_t size)
  115. {
  116.     return _bresize(segm, memblock, size, LMEM_FIXED);
  117. }
  118.  
  119. /* Expand or shrink an allocated block, possibly moving it */
  120. void _based(void) *_brealloc(_segment segm, 
  121.     void _based(void) *memblock, size_t size)
  122. {
  123.     return _bresize(segm, memblock, size, LMEM_MOVEABLE);
  124. }
  125.  
  126. /* Return the size of a previously allocated block */
  127. size_t _bmsize(_segment segm, void _based(void) *memblock)
  128. {
  129.     WORD ret;
  130.     SET_DS(segm);
  131.     ret = LocalSize((WORD) memblock);
  132.     RESTORE_DS(segm);
  133.     return ret;
  134. }
  135.  
  136.